/*
 * Wazuh Module for routing messages.
 * Copyright (C) 2015, Wazuh Inc.
 * May 1, 2023
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#include "wm_vulnerability_scanner.h"
#include "external/cJSON/cJSON.h"
#include "sym_load.h"
#include "vulnerability_scanner.h"
#include "config/indexer-config.h"

static void* wm_vulnerability_scanner_main(wm_vulnerability_scanner_t * data);
static void wm_vulnerability_scanner_destroy(wm_vulnerability_scanner_t * data);
static void wm_vulnerability_scanner_stop(wm_vulnerability_scanner_t * data);
cJSON* wm_vulnerability_scanner_dump(wm_vulnerability_scanner_t * data);

void* vulnerability_scanner_module = NULL;
vulnerability_scanner_start_func vulnerability_scanner_start_ptr = NULL;
vulnerability_scanner_stop_func vulnerability_scanner_stop_ptr = NULL;

const wm_context WM_VULNERABILITY_SCANNER_CONTEXT = {
    .name = "vulnerability_scanner",
    .start = (wm_routine)wm_vulnerability_scanner_main,
    .destroy = (void (*)(void*))wm_vulnerability_scanner_destroy,
    .dump = (cJSON * (*)(const void*)) wm_vulnerability_scanner_dump,
    .sync = NULL,
    .stop = (void (*)(void*))wm_vulnerability_scanner_stop,
    .query = NULL,
};

static void wm_vulnerability_scanner_log_config(cJSON * config_json)
{
    if (config_json) {
        char * config_str = cJSON_PrintUnformatted(config_json);
        if (config_str) {
            mtdebug1(WM_VULNERABILITY_SCANNER_LOGTAG, "%s", config_str);
            cJSON_free(config_str);
        }
    }
}

void* wm_vulnerability_scanner_main(wm_vulnerability_scanner_t * data)
{
    mtinfo(WM_VULNERABILITY_SCANNER_LOGTAG, "Starting vulnerability_scanner module.");
    if (vulnerability_scanner_module = so_get_module_handle("vulnerability_scanner"), vulnerability_scanner_module)
    {
        vulnerability_scanner_start_ptr =
            so_get_function_sym(vulnerability_scanner_module, "vulnerability_scanner_start");
        vulnerability_scanner_stop_ptr =
            so_get_function_sym(vulnerability_scanner_module, "vulnerability_scanner_stop");

        // Check for missing configurations. These configurations may miss when using the old deprecated VD config.
        if (!cJSON_GetObjectItem(data->vulnerability_detection, "enabled"))
        {
            cJSON_AddStringToObject(data->vulnerability_detection, "enabled", "yes");
        }
        if (!cJSON_GetObjectItem(data->vulnerability_detection, "index-status"))
        {
            cJSON_AddStringToObject(data->vulnerability_detection, "index-status", "yes");
        }
        if (!cJSON_GetObjectItem(data->vulnerability_detection, "feed-update-interval"))
        {
            cJSON_AddStringToObject(data->vulnerability_detection, "feed-update-interval", "60m");
        }
        if (!cJSON_GetObjectItem(data->vulnerability_detection, "clusterName"))
        {
            char* cluster_name = get_cluster_name();
            cJSON_AddStringToObject(data->vulnerability_detection, "clusterName", cluster_name);
            os_free(cluster_name);
        }

        if (vulnerability_scanner_start_ptr)
        {
            cJSON *config_json = cJSON_CreateObject();
            cJSON_AddItemToObject(config_json, "vulnerability-detection", cJSON_Duplicate(data->vulnerability_detection, TRUE));
            cJSON_AddNumberToObject(config_json, "wmMaxEps", wm_max_eps);
            cJSON_AddNumberToObject(config_json, "translationLRUSize", getDefine_Int("vulnerability-detection", "translation_lru_size", 1, 100000));
            cJSON_AddNumberToObject(config_json, "osdataLRUSize", getDefine_Int("vulnerability-detection", "osdata_lru_size", 1, 100000));
            cJSON_AddNumberToObject(config_json, "managerDisabledScan", getDefine_Int("vulnerability-detection", "disable_scan_manager", 0, 1));

            char* manager_node_name = get_node_name();

            cJSON_AddStringToObject(config_json, "managerNodeName", manager_node_name);

            os_free(manager_node_name);

            if(indexer_config == NULL)
            {
                cJSON_AddItemToObject(config_json, "indexer", cJSON_CreateObject());
            }
            else
            {
                cJSON_AddItemToObject(config_json, "indexer", cJSON_Duplicate(indexer_config, TRUE));
            }
            wm_vulnerability_scanner_log_config(config_json);
            vulnerability_scanner_start_ptr(mtLoggingFunctionsWrapper, config_json);
            cJSON_Delete(config_json);
        }
        else
        {
            mtwarn(WM_VULNERABILITY_SCANNER_LOGTAG, "Unable to start vulnerability_scanner module.");
            return NULL;
        }
    }
    else
    {
        mtwarn(WM_VULNERABILITY_SCANNER_LOGTAG, "Unable to load vulnerability_scanner module.");
        return NULL;
    }

    return NULL;
}

void wm_vulnerability_scanner_destroy(wm_vulnerability_scanner_t * data)
{
    free(data);
}

void wm_vulnerability_scanner_stop(__attribute__((unused))wm_vulnerability_scanner_t *data)
{
    mtinfo(WM_VULNERABILITY_SCANNER_LOGTAG, "Stopping vulnerability_scanner module.");
    if (vulnerability_scanner_stop_ptr)
    {
        vulnerability_scanner_stop_ptr();
    }
    else
    {
        mtwarn(WM_VULNERABILITY_SCANNER_LOGTAG, "Unable to stop vulnerability_scanner module.");
    }
}

cJSON* wm_vulnerability_scanner_dump(wm_vulnerability_scanner_t * data)
{
    cJSON *root = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "vulnerability-detection", cJSON_Duplicate(data->vulnerability_detection, TRUE));
    cJSON_DeleteItemFromObject(cJSON_GetObjectItem(root, "vulnerability-detection"), "indexer-status");
    cJSON_DeleteItemFromObject(cJSON_GetObjectItem(root, "vulnerability-detection"), "cti-url");
    cJSON_DeleteItemFromObject(cJSON_GetObjectItem(root, "vulnerability-detection"), "clusterName");

    return root;
}
